package ru.vt;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import ru.chezclif.lern.conread.Preconditions;
import ru.chezclif.lern.conread.PropertyElements;
import ru.chezclif.lern.conread.PropertyManager;
import ru.chezclif.lern.conread.readers.PropertyReader;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Vit
 *         Бин, предназначенный для загрузки конфигов на сервер для дальнейшего парсинга
 */
public class SettingsForConfig {
    /**
     * Переменная для передаваямого от клиента файла
     */
    private UploadedFile uploadedFile = null;
    /**
     * Переменная показывающая абсолютный путь до загруженного файла
     */
    private String filePath = "";
    /**
     * Переменная показывающая название файла до загрузки на сервер
     */
    private String oldFileName = "";
    /**
     * Название типа конфига: xml, properties, ini
     */
    private String protocol = "";
    /**
     * Показывает, выбран ли тип конфига
     */
    private Boolean shosedProtocol = false;
    /**
     * Показывает факт успешной передачи файла на сервер
     */
    private Boolean uploaded = false;
    /**
     * Название выбранного конфига для его редактирования
     */
    private String nowUsedConfig = "";
    /**
     * Хранилище с конфигами
     */
    private List<Config> configList = new ArrayList<Config>();
    /**
     * Проежуточный конфиг для манипуляций
     */
    private Config deltaConfig;
    /**
     * Хранит позицию элемента configList, с которого взяли копию для редактирования
     */
    private int positionOfSavedConfig;
    /**
     * Путь до сформированного файла для скачивания
     */
    private String pathToDownloadFile = "";
    /**
     * Флаг, позволяющтй/запрещающий скачивать сформированный файл
     */
    private Boolean flagForDownload = false;
    /**
     * Переменная показывает, что загружать справа от меню
     */
    private int mode = 0;

    /**
     * Переход к стартовой странице
     */
    public void goDefaultPage() {
        mode = 0;
    }

    /**
     * Переход к странице с загрузкой конфига
     */
    public void goLoadPage() {
        mode = 1;
    }

    /**
     * Переход к странице спредварительным просмотром
     */
    public void goPresentPage() {
        presentSettings();
        mode = 2;
    }

    /**
     * Переход к странице редактирования конфига
     */
    public void goOperationsPage() {
        copyToDeltaConfig();
        mode = 3;
        // String i = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("chosedParam").toString();
        //System.out.println("Mode is : "+i);
    }

    /**
     * Переход к странице выгрузки конфига
     */
    public void goDownloadPage() {
        saveEditedConfig();
        protocol = "";
        flagForDownload = false;
        mode = 4;
    }

    public void clearSettings() {
        File fileForDel = new File(filePath);
        if (fileForDel != null) {
            fileForDel.delete();
        }
        filePath = "";
        oldFileName = "";
        shosedProtocol = false;
        uploaded = false;
        protocol = "";
        nowUsedConfig = "";
        flagForDownload = false;
        positionOfSavedConfig = -1;
    }

    /**
     * Загрузка файла на сервер
     */
    public void uploadFile() {
        String prefix = FilenameUtils.getBaseName(uploadedFile.getName());
        String suffix = FilenameUtils.getExtension(uploadedFile.getName());
        oldFileName = " " + prefix + "." + suffix + " ";
        File file = null;
        OutputStream output = null;
        try {
            // Create file with unique name in upload folder and write to it.
            file = File.createTempFile(prefix + "_", "." + suffix, new File("c://uploadconfig"));
            output = new FileOutputStream(file);
            IOUtils.copy(uploadedFile.getInputStream(), output);
            filePath = file.getAbsolutePath();
            uploaded = true;
        } catch (IOException e) {
            // Cleanup.
            if (file != null) file.delete();
            // Always log stacktraces (with a real logger).
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(output);
        }
    }

    /**
     * СОздание промежуточного конфига для предварительного просмотра
     */
    public void presentSettings() {
        deltaConfig = new Config(oldFileName, Config.stringPseudoProtConvert(protocol, filePath));
    }

    /**
     * Очистка промежуточного конфига м перменных для страниц ознакомления/редактирования
     */
    public void cancelManipulations() {
        deltaConfig = null;
        clearSettings();
        goDefaultPage();
    }

    /**
     * Утвержденный конфиг сохранятеся в хранилище, промежуточный конфиг очищается
     */
    public void extractSettings() {
        deltaConfig = null;
        configList.add(
                new Config(
                        oldFileName, Config.stringPseudoProtConvert(protocol, filePath)));
        clearSettings();
        goDefaultPage();
    }

    /**
     * Создание временной копии конфига из хранилища
     */
    public void copyToDeltaConfig() {
        deltaConfig = null;
        for (Config config : configList) {
            if (config.getConfigName().equals(nowUsedConfig)) {
                deltaConfig = new Config(config);
                positionOfSavedConfig = configList.indexOf(config);
                break;
            }
        }
    }

    /**
     * СОхранение из промежуточного конфига в хранилище, с удалением элемента, с которого ранее была сделана копия
     */
    public void saveEditedConfig() {
        configList.remove(positionOfSavedConfig);
        configList.add(deltaConfig);
    }

    /**
     * Конвертирует из протокола в расшмирение файла
     *
     * @param protocol Протокол
     */
    public String convertFromProtToExt(String protocol) {
        Preconditions.notNull(protocol);
        Preconditions.notBlank(protocol);
        if (protocol.equals("xml")) return ".xml";
        if (protocol.equals("ini")) return ".ini";
        if (protocol.equals("props")) return ".properties";
        return "";
    }

    /**
     * СОхранение файла в папку, выгрузка пользователю через сервлет и очистка переменных
     */
    public void saveFile() {
        //copyToDeltaConfig();
        // nowUsedConfig=deltaConfig.getConfigName();
        PropertyManager propertyManagerAccess = new PropertyManager();
        PropertyReader propertyReader = propertyManagerAccess.getPropertyReader();
        for (PropertyElements propertyElements : deltaConfig.getConfigList().getElements()) {
            propertyReader.setSetting(propertyElements.getKey(), propertyElements.getValue());
        }
        propertyReader.setHeaderComment(deltaConfig.getHeaderComment());
        propertyReader.setFooterComment(deltaConfig.getFooterComment());
        //Зманеа nowUsedConfig на
        pathToDownloadFile = deltaConfig.getConfigName().trim() + convertFromProtToExt(protocol);
        propertyReader.saveFile(protocol + "://" + "c:\\downloadconfig\\" + pathToDownloadFile);
        flagForDownload = true;
    }

    /**
     * Вернуться на главную страницу после скачивания файла
     */
    public void goDefPageAfterDownload() {
        clearSettings();
        File fileForDel = new File("c:\\downloadconfig\\" + pathToDownloadFile);
        if (fileForDel != null) {
            fileForDel.delete();
        }
        pathToDownloadFile = "";
        flagForDownload = false;
        deltaConfig = null;
        mode = 0;
    }

    //Геттеры и сеттеры
    public int getMode() {
        return mode;
    }

    public void setMode(int mode) {
        Preconditions.notNull(mode);
        this.mode = mode;
    }

    public Boolean getShosedProtocol() {
        return shosedProtocol;
    }

    public void setShosedProtocol(Boolean shosedProtocol) {
        Preconditions.notNull(shosedProtocol);
        this.shosedProtocol = shosedProtocol;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        Preconditions.notNull(filePath);
        Preconditions.notBlank(filePath);
        this.filePath = filePath;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        Preconditions.notNull(protocol);
        Preconditions.notBlank(protocol);
        this.protocol = protocol;
        shosedProtocol = true;
    }

    public String getOldFileName() {
        return oldFileName;
    }

    public void setOldFileName(String oldFileName) {
        Preconditions.notNull(oldFileName);
        this.oldFileName = oldFileName;
    }

    public UploadedFile getUploadedFile() {
        return uploadedFile;
    }

    public void setUploadedFile(UploadedFile uploadedFile) {
        Preconditions.notNull(uploadedFile);
        this.uploadedFile = uploadedFile;
    }

    public Boolean getUploaded() {
        return uploaded;
    }

    public void setUploaded(Boolean uploaded) {
        Preconditions.notNull(uploaded);
        this.uploaded = uploaded;
    }

    public Config getDeltaConfig() {
        return deltaConfig;
    }

    public List<Config> getConfigList() {
        return configList;
    }

    public String getNowUsedConfig() {
        return nowUsedConfig;
    }

    public void setNowUsedConfig(String nowUsedConfig) {
        Preconditions.notNull(nowUsedConfig);
        this.nowUsedConfig = nowUsedConfig;
    }

    public Boolean getFlagForDownload() {
        return flagForDownload;
    }

    public void setFlagForDownload(Boolean flagForDownload) {
        Preconditions.notNull(flagForDownload);
        this.flagForDownload = flagForDownload;
    }

    public String getPathToDownloadFile() {
        return pathToDownloadFile;
    }

    public void setPathToDownloadFile(String pathToDownloadFile) {
        Preconditions.notNull(pathToDownloadFile);
        this.pathToDownloadFile = pathToDownloadFile;
    }
}
